import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_rider/api/api.dart';
import 'package:flutter_rider/config.dart';
import 'package:flutter_rider/main/api/app_api.dart';
import 'package:flutter_rider/utils/device_utils.dart';

/// 捕获全局异常，进行统一处理。
void handleError(void Function() body) {
  /// 重写Flutter异常回调 FlutterError.onError
  FlutterError.onError = (FlutterErrorDetails details) {
    if (kDebugMode) {
      // debug时，直接将异常信息打印。
      FlutterError.dumpErrorToConsole(details);
    } else {
    // release时，将异常交由zone统一处理。
    Zone.current.handleUncaughtError(details.exception, details.stack!);
    }
  };

  /// 使用runZonedGuarded捕获Flutter未捕获的异常
  runZonedGuarded(body, (Object error, StackTrace stackTrace) async {
    await _reportError(error, stackTrace);
  });
}

Future<void> _reportError(Object error, StackTrace stackTrace) async {
  if (kDebugMode) {
    debugPrintStack(
      stackTrace: stackTrace,
      label: error.toString(),
      maxFrames: 100,
    );
  } else {
  // 将异常信息收集并上传到服务器。可以直接使用类似`flutter_bugly`插件处理异常上报。
  Iterable<String> lines = stackTrace.toString().trimRight().split('\n');
  var maxFrames = 30;
  lines = lines.take(maxFrames);
  var json = {};

  var errorInfo = error.toString();

  if (errorInfo.contains("Software caused connection abort, errno = 103") ||
      errorInfo.contains("Write failed (OS Error: Broken pipe, errno = 32") ||
      errorInfo.contains(
          "Bad file descriptor (OS Error: Bad file descriptor, errno = 9") ||
      errorInfo.contains(
          "Connection timed out (OS Error: Connection timed out, errno = 110)") ||
      errorInfo.contains(
          "CameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.)")) {
    //过滤一些第三方SDK的错误，不上报了，TCP网络波动就会捕获到这个异常
    return;
  }

  var errInfo =
      "\n智行助手版本号:${DeviceUtils.instance.packageInfo.version}${DeviceUtils.instance.getSystemInfo()}\nerror: \n${error.toString()} \nstackTrace: \n${FlutterError.defaultStackFilter(lines).join('\n')}";

  json["err_info"] = errInfo;

  Api.post(AppApi.report, json, (data, response) {});
  }
}
